#include "app_release.h"

#define APP_RELEASE_SW_PIN LL_GPIO_PIN_6
#define APP_RELEASE_SW_PORT GPIOB

#define APP_RELEASE_ADC_PIN LL_GPIO_PIN_5
#define APP_RELEASE_ADC_PORT GPIOB

#define STUCK_RETRY_MAX_COUNTS (0x03)

#define RELEASE_TIMEOUT (5 * 1000)
#define STUCK_COUNTDOWN_TIME (5 * 1000)
#define STUCK_REVERSED_TIME (3 * 1000)
#define SENSOR_TIMEOUT_TIME (5 * 1000)

#define JAM_THRESHOLD_VALUE (0x0E60)

enum
{
    DIRECTION_NONE,
    DIRECTION_LEFT,
    DIRECTION_WAIT,
    DIRECTION_RIGHT,
    DIRECTION_STUCK,
};

enum
{
    GRAIN_FULL,
    GRAIN_EMPTY,
};

typedef struct
{
    struct
    {
        unsigned char work;
        unsigned char value;
        unsigned char start;
    } feed;

    struct
    {
        unsigned char value;
    } result;

    struct
    {
        unsigned int time;
    } motor;

    struct
    {
        unsigned char direction;
        unsigned char count;
        unsigned int start;
        unsigned int time;
    } stuck;

    struct
    {
        unsigned char wait; // 出粮口堵塞等待检测
        unsigned int time;
    } jam;

    struct
    {
        unsigned char state;
    } grain;

    struct
    {
        unsigned char wait;
    } notify;
} release_mgr_t;

static release_mgr_t sg_release_mgr = {0x00};
static void app_release_stuck_detect_handler(void);
static void app_release_clear_stuck(void);

void app_release_init(void)
{
    // release sw detect
    LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOF);
    LL_GPIO_InitTypeDef GPIO_InitStruct = {0x00};
    GPIO_InitStruct.Pin = APP_RELEASE_SW_PIN;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
    LL_GPIO_Init(APP_RELEASE_SW_PORT, &GPIO_InitStruct);

    app_motor_cb_register(app_release_motor_cb_handler);
    // app_motor_release_result_cb_register(app_release_lack_handler);   //lack full
    app_motor_jam_cb_register(app_release_stuck_detect_handler); // Reversal
    sg_release_mgr.feed.work = 0x00;
    sg_release_mgr.feed.value = 0x00;
}

// static inline void app_release_ir_tx_start(void)
//{
//     LL_GPIO_SetOutputPin(APP_RELEASE_CTRL_PORT, APP_RELEASE_CTRL_PIN);
// }

// static inline void app_release_ir_tx_stop(void)
//{
//     LL_GPIO_ResetOutputPin(APP_RELEASE_CTRL_PORT, APP_RELEASE_CTRL_PIN);
// }

// static unsigned char app_release_is_jam(void)
//{
//     // app_release_ir_tx_start();
//     LL_GPIO_SetOutputPin(APP_RELEASE_CTRL_PORT, APP_RELEASE_CTRL_PIN);
//     int value = app_adc_convert(LL_ADC_CHANNEL_5);
//     LL_GPIO_ResetOutputPin(APP_RELEASE_CTRL_PORT, APP_RELEASE_CTRL_PIN);

//    if (value > JAM_THRESHOLD_VALUE) {
//        return 0x01;
//    }

//    return 0x00;
//}

static unsigned char app_release_set_fault(unsigned char fault)
{
    if ((dp_obj->fault & (1 << fault)) == 0)
    {
        dp_obj->fault |= (1 << fault);
        app_led_toggle(APP_LED_JAM, APP_TOGGLE_SLOW_TIME, 0);
        return 0x01;
    }

    return 0x00;
}

static unsigned char app_release_clear_fault(unsigned char fault)
{
    if ((dp_obj->fault & (1 << fault)))
    {
        dp_obj->fault &= ~(1 << fault);
        return 0x01;
    }

    return 0x00;
}

// void app_release_set_value(unsigned char value)
// {
//     if (sg_release_mgr.feed.value != 0x00)
//     {
//         return;
//     }

//     // 当电源到达关闭电压时 不再执行喂食
//     if (app_power_is_off())
//     {
//         return;
//     }

//     //    if (app_release_is_jam()) {
//     //        if (app_release_set_fault(FOOD_JAM)) {
//     //            app_dp_fault_notify();
//     //        }
//     //        app_led_toggle(APP_LED_BAT, APP_TOGGLE_SLOW_TIME, 0);
//     //
//     //        return ;
//     //    }

//     // 卡粮中
//     if (sg_release_mgr.stuck.direction != DIRECTION_NONE)
//     {
//         return;
//     }

//     // 清除卡粮
//     app_release_clear_stuck();
//     sg_release_mgr.feed.value = value;
// }

static void app_release_clear_value(void)
{
    sg_release_mgr.feed.start = 0x00;
    sg_release_mgr.feed.value = 0x00;
    sg_release_mgr.feed.work = 0x00;
}

static void app_release_start_feed(void)
{
    sg_release_mgr.feed.start = app_sys_ticks;
    sg_release_mgr.feed.work = 0x01;

    sg_release_mgr.motor.time = app_sys_ticks;
    sg_release_mgr.result.value = 0x00;
    sg_release_mgr.grain.state = GRAIN_EMPTY;

    // app_record_set_play();
    app_motor_forward();

    dp_obj->state = FEED_FEEDING;
    app_dp_feed_state_notify();
}

static void app_release_clear_result(void)
{
    sg_release_mgr.result.value = 0x00;
}

static void app_release_set_result(unsigned char val)   //角度开关闭合 
{
    if (sg_release_mgr.feed.value == 0x00)
    {
        app_motor_stop();
        app_release_clear_value();
        app_release_clear_result();
        return;
    }

    sg_release_mgr.result.value += 0x01;
    sg_release_mgr.motor.time = app_sys_ticks;

    if (sg_release_mgr.feed.value == sg_release_mgr.result.value)
    {
        app_motor_stop();
        app_release_clear_value();

        dp_obj->result = sg_release_mgr.result.value;
        sg_release_mgr.notify.wait = 0x01;
        sg_release_mgr.jam.wait = 0x01; // 出粮口 堵塞 等待检测

        app_release_clear_result();
    }
    else
    {
        sg_release_mgr.grain.state = GRAIN_EMPTY;
    }
}

void app_release_motor_cb_handler(void) //角度开关闭合
{
    if (sg_release_mgr.stuck.direction != DIRECTION_NONE)
    {
        return;
    }

    sg_release_mgr.motor.time = app_sys_ticks;
    app_release_set_result(0x01);
}

static void app_release_feed_handler(void)  //开始出粮
{
    // 未设置喂食或卡粮中
    if (sg_release_mgr.feed.value == 0x00 || sg_release_mgr.stuck.direction != DIRECTION_NONE)
    {
        return;
    }

    // 出粮中
    if (sg_release_mgr.feed.work)
    {
        return;
    }

    app_release_start_feed();
}

static void app_release_stuck_detect_handler(void)  //角度开关未检测  超时
{
    if (sg_release_mgr.stuck.direction == DIRECTION_NONE)
    {
        sg_release_mgr.stuck.count += 0x01;
        sg_release_mgr.stuck.direction = DIRECTION_RIGHT;
        sg_release_mgr.stuck.start = app_sys_ticks;
        sg_release_mgr.stuck.time = app_sys_ticks;

        app_motor_reverse();
    }
}

static void app_release_clear_stuck(void)
{
    sg_release_mgr.stuck.count = 0x00;
    sg_release_mgr.stuck.direction = DIRECTION_NONE;
}

static void app_release_stuck_handler(void)
{
    if (sg_release_mgr.feed.work == 0x00)
    {
        return;
    }

    // 反转
    if (sg_release_mgr.stuck.direction == DIRECTION_RIGHT)
    {
        if (time_after(app_sys_ticks, sg_release_mgr.stuck.time + STUCK_REVERSED_TIME))
        {
            app_motor_stop();
            if (sg_release_mgr.stuck.count < STUCK_RETRY_MAX_COUNTS)
            {
                sg_release_mgr.stuck.direction = DIRECTION_WAIT;
                sg_release_mgr.stuck.time = app_sys_ticks;
            }
            else
            {
                if (app_release_set_fault(DESICCANT))
                {
                    app_dp_fault_notify();
                }

                app_release_clear_value();
                app_release_clear_result();
                app_release_clear_stuck();
            }
        }
    }

    // 倒计时
    if (sg_release_mgr.stuck.direction == DIRECTION_WAIT)
    {
        if (time_after(app_sys_ticks, sg_release_mgr.stuck.time + STUCK_COUNTDOWN_TIME))
        {
            sg_release_mgr.stuck.direction = DIRECTION_NONE;
            sg_release_mgr.stuck.time = app_sys_ticks;

            sg_release_mgr.motor.time = app_sys_ticks;
            // 再次 正转
            app_motor_forward();
        }
    }
}

static void app_release_jam_handler(void)
{
    if (sg_release_mgr.feed.work)
    {
        return;
    }

    if (dev_obj->type == BAT_TYPE && sg_release_mgr.jam.wait == 0)
    {
        // 当前电池供电，并且没有设置堵粮 检测等待标志
        return;
    }

    if (time_after(app_sys_ticks, sg_release_mgr.jam.time + 1000) && app_release_is_finished())
    {
        //        if (app_release_is_jam()) {
        //            if (app_release_set_fault(FOOD_JAM)) {
        //                app_dp_fault_notify();
        //            }
        //        } else {
        //            if (app_release_clear_fault(FOOD_JAM)) {
        //                app_dp_fault_notify();
        //            }
        //        }

        sg_release_mgr.jam.time = app_sys_ticks;
        sg_release_mgr.jam.wait = 0x00;
    }
}

void app_release_lack_handler(void)
{
    if (sg_release_mgr.feed.work == 0)
    {
        return;
    }

    //    LL_GPIO_SetOutputPin(APP_RELEASE_CTRL_PORT, APP_RELEASE_CTRL_PIN);
    //    int value = app_adc_convert(LL_ADC_CHANNEL_5);
    //    LL_GPIO_ResetOutputPin(APP_RELEASE_CTRL_PORT, APP_RELEASE_CTRL_PIN);

    //    if (value > JAM_THRESHOLD_VALUE) {
    //        sg_release_mgr.grain.state = GRAIN_FULL;
    //    }
}

static void app_release_noitfy_handler(void)
{
    if (sg_release_mgr.notify.wait)
    {
        sg_release_mgr.notify.wait = 0x00;

        if (dev_obj->tuya_net == TUYA_NET_OK)
        {
            app_dp_feed_report_notify();
        }
        else
        {
            app_time_rec_write(dp_obj->result);
        }
        app_release_clear_result();

        // if (app_release_clear_fault(DESICCANT) || app_release_clear_fault(FOOD_RUN_OUT))
        // {
        //     app_dp_fault_notify();
        // }
        if (app_release_clear_fault(DESICCANT))
        {
            app_dp_fault_notify();
        }        
        // 出粮口光电管 缺粮上报
        //  if (sg_release_mgr.grain.state == GRAIN_EMPTY) {
        //      if (app_release_set_fault(FOOD_SHORTAGES)) {
        //          app_dp_fault_notify();
        //      }
        //      app_led_toggle(APP_LED_BAT, APP_TOGGLE_SLOW_TIME, 0x00);
        //  } else {
        //      if (app_release_clear_fault(FOOD_SHORTAGES)) {
        //          app_dp_fault_notify();
        //      }
        //  }
    }

    if (app_release_is_finished() && dp_obj->state == FEED_FEEDING)
    {
        dp_obj->state = FEED_DONE;
        app_dp_feed_state_notify();
    }
}

static void app_release_sensor_handler(void)
{
    if (sg_release_mgr.feed.work && sg_release_mgr.stuck.direction == DIRECTION_NONE)
    {
        if (time_after(app_sys_ticks, (sg_release_mgr.motor.time + SENSOR_TIMEOUT_TIME)))
        {
            app_release_clear_result();
            app_release_clear_value();
            app_release_clear_stuck();
            app_motor_stop();
            app_release_stuck_detect_handler();
            // if (app_release_set_fault(FOOD_RUN_OUT)) {
            //     app_dp_fault_notify();
            // }
            // app_led_toggle(APP_LED_BAT, APP_TOGGLE_SLOW_TIME, 0);
        }
    }
}

void app_release_task(void)
{
    if (dev_obj->factory.state != FACTORY_NONE)
    {
        return;
    }
    app_release_feed_handler();
    app_release_stuck_handler(); // Reversal handle
    // app_release_jam_handler();      //lack full handle
    app_release_noitfy_handler();
    app_release_sensor_handler(); // feed no detect sw...  timeout
}

unsigned char app_release_is_finished(void)
{
    if (sg_release_mgr.feed.value == 0x00 && app_motor_is_stopped())
    {
        return 0x01;
    }

    return 0x00;
}

unsigned int drv_release_sw_read_level(void)
{
    return LL_GPIO_IsInputPinSet(APP_RELEASE_SW_PORT, APP_RELEASE_SW_PIN);
}
